home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / iritsm3s.zip / INPTEVAL.C < prev    next >
C/C++ Source or Header  |  1992-01-30  |  66KB  |  1,884 lines

  1. /*****************************************************************************
  2. *   "Irit" - the 3d polygonal solid modeller.                     *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.2, Mar. 1990   *
  5. ******************************************************************************
  6. *   Module to evaluate the binary tree generated by the InptPrsr module.     *
  7. *   All the objects are handled the same but the numerical one, which is     *
  8. * moved as a RealType and not as an object (only internally within this         *
  9. * module) as it is frequently used and consumes much less memory this way.   *
  10. *   Note this module is par of InptPrsr module and was splited only because  *
  11. * of text file sizes problems...                         *
  12. *****************************************************************************/
  13.  
  14. #ifdef __MSDOS__
  15. #include <alloc.h>
  16. #include <dir.h>
  17. #endif /* __MSDOS__ */
  18.  
  19. #include <stdio.h>
  20. #include <ctype.h>
  21. #include <math.h>
  22. #include <string.h>
  23. #include "program.h"
  24. #include "allocate.h"
  25. #include "attribut.h"
  26. #include "convex.h"
  27. #include "ctrl-brk.h"
  28. #include "dataprsr.h"
  29. #include "dosintr.h"
  30. #include "freeform.h"
  31. #include "geomat3d.h"
  32. #include "geomvals.h"
  33. #include "graphgen.h"
  34. #include "inptprsg.h"
  35. #include "inptprsl.h"
  36. #include "matherr.h"
  37. #include "objects.h"
  38. #include "overload.h"
  39. #include "primitiv.h"
  40. #include "viewobj.h"
  41. #include "windows.h"
  42.  
  43. InptPrsrEvalErrType IPGlblEvalError = IPE_NO_ERR;/* Global used by EvalTree. */
  44. extern char IPGlblCharData[LINE_LEN_LONG];    /* Used for both parse & eval. */
  45.  
  46. /*   I prefer to put the declarations of static functions just before the    */
  47. /* function themselves, but the tables below needs them so...             */
  48. static int FetchParameters(ParseTree *Root, int NumParams, int Level,
  49.                              ParseTree *Params[]);
  50. static void PrintHelp(char *HelpHeader);
  51. static void IfCondition(ParseTree *Left, ParseTree *Cond, ParseTree *Right,
  52.                               ParseTree *PBody);
  53. static void ForLoop(ParseTree *PStart, ParseTree *PInc, ParseTree *PEnd,
  54.                             ParseTree *PBody);
  55. static ObjectStruct *GenObjectList(ParseTree *PObjParams);
  56. static ObjectStruct *CtlPtFromParams(ParseTree *PObjParams);
  57. static int CountNumExpressions(ParseTree *Root);
  58. static ParseTree *FetchExpression(ParseTree *Root, int i, int n);
  59. static int RetrieveMathError(void);
  60. static int CountNumParameters(ParseTree *Root);
  61. static ParseTree *FetchParameter(ParseTree *Root, int i, int n);
  62. static int FuncParamMismatch(ParseTree *Root);
  63. static void LocalPrintTree(ParseTree *Root, int Level, char *Str);
  64. static void RebindVariable(ParseTree *Root, ObjectStruct *PObj);
  65. static int RetrieveMathError(void);
  66.  
  67. /* Although the type of parameters is specified (for InptPrsrTypeCheck rtn)  */
  68. /* All the parameters to the following dispatched functions are passed by    */
  69. /* address. There is a problem in TurboC (ANSI C?) that all the real types   */
  70. /* are passed as double, even if the are float. As RealType may be float,    */
  71. /* the problems is hidden by passing parameters by address...             */
  72.  
  73. NumFuncTableType NumFuncTable[] = {
  74.     { "ACOS",    ARCCOS,    acos,        1,    { NUMERIC_EXPR } },
  75.     { "ASIN",    ARCSIN,    asin,        1,    { NUMERIC_EXPR } },
  76.     { "ATAN2",    ARCTAN2, atan2,        2,    { NUMERIC_EXPR, NUMERIC_EXPR } },
  77.     { "ATAN",    ARCTAN,    atan,        1,    { NUMERIC_EXPR } },
  78.     { "COS",    COS,    cos,        1,    { NUMERIC_EXPR } },
  79.     { "EXP",    EXP,    exp,        1,    { NUMERIC_EXPR } },
  80.     { "ABS",    FABS,    fabs,        1,    { NUMERIC_EXPR } },
  81.     { "LN",    LN,    log,        1,    { NUMERIC_EXPR } },
  82.     { "LOG",    LOG,    log10,        1,    { NUMERIC_EXPR } },
  83.     { "SIN",    SIN,    sin,        1,    { NUMERIC_EXPR } },
  84.     { "SQRT",    SQRT,    sqrt,        1,    { NUMERIC_EXPR } },
  85.     { "TAN",    TAN,    tan,        1,    { NUMERIC_EXPR } },
  86.     { "CPOLY",    CPOLY,    PolyCountPolys,    1,    { POLY_EXPR } },
  87.     { "AREA",    AREA,    PolyObjectArea,    1,    { POLY_EXPR } },
  88.     { "VOLUME",    VOLUME,    PolyObjectVolume, 1,    { POLY_EXPR } },
  89.     { "TIME",    TIME,    DosGetTime,    1,    { NUMERIC_EXPR } },
  90. };
  91. int NumFuncTableSize = sizeof(NumFuncTable) / sizeof(NumFuncTableType);
  92.  
  93. ObjFuncTableType ObjFuncTable[] = {
  94.     { "VECTOR",      VECTOR,    GenVecObject,        3,    { NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
  95.     { "CTLPT",      CTLPT,    CtlPtFromParams,    ANY_PARAM_NUM, { 0 } },
  96.     { "ROTX",      ROTX,        GenMatObjectRotX,    1,    { NUMERIC_EXPR } },
  97.     { "ROTY",      ROTY,        GenMatObjectRotY,    1,    { NUMERIC_EXPR } },
  98.     { "ROTZ",      ROTZ,        GenMatObjectRotZ,    1,    { NUMERIC_EXPR } },
  99.     { "TRANS",      TRANS,    GenMatObjectTrans,    1,    { VECTOR_EXPR } },
  100.     { "SCALE",      SCALE,    GenMatObjectScale,    1,    { VECTOR_EXPR } },
  101.     { "BOX",      BOX,        GenBOXObject,        4,    { VECTOR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
  102.     { "GBOX",      GBOX,        GenGBOXObject,        4,    { VECTOR_EXPR, VECTOR_EXPR, VECTOR_EXPR, VECTOR_EXPR } },
  103.     { "CONE",      CONE,        GenCONEObject,        3,    { VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR } },
  104.     { "CON2",      CONE2,    GenCONE2Object,        4,    { VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
  105.     { "CYLIN",      CYLIN,    GenCYLINObject,        3,    { VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR } },
  106.     { "SPHERE",      SPHERE,    GenSPHEREObject,    2,    { VECTOR_EXPR, NUMERIC_EXPR } },
  107.     { "TORUS",      TORUS,    GenTORUSObject,        4,    { VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
  108.     { "CIRCPOLY", CIRCPOLY,    GenPLANEObject,        3,    { VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR } },
  109.     { "POLY",      POLY,        GenPOLYGONObject,    1,    { OLST_EXPR } },
  110.     { "CROSSEC",  CROSSEC,    GenCROSSECObject,    1,    { POLY_CURVE_EXPR } },
  111.     { "SURFREV",  SURFREV,    GenSURFREVObject,    1,    { POLY_CURVE_EXPR } },
  112.     { "EXTRUDE",  EXTRUDE,    GenEXTRUDEObject,    2,    { POLY_CURVE_EXPR, VECTOR_EXPR } },
  113.     { "LIST",      LIST,        GenObjectList,        ANY_PARAM_NUM, { 0 } },
  114.     { "LOAD",     LOAD,        DataPrsrGetObjects,    1,    { STRING_EXPR } },
  115.     { "CONVEX",      CONVEX,    ConvexPolyObjectN,    1,    { POLY_EXPR } },
  116.     { "SBEZIER",  SBEZIER,    GenBezierSurfaceObject, 1,    { OLST_EXPR } },
  117.     { "CBEZIER",  CBEZIER,    GenBezierCurveObject,    1,    { OLST_EXPR } },
  118.     { "SBSPLINE", SBSPLINE,    GenBsplineSurfaceObject, 4,    { NUMERIC_EXPR, NUMERIC_EXPR, OLST_EXPR, OLST_EXPR } },
  119.     { "CBSPLINE", CBSPLINE,    GenBsplineCurveObject,    3,    { NUMERIC_EXPR, OLST_EXPR, OLST_EXPR } },
  120.     { "SEVAL",    SEVAL,    EvalSurfaceObject,    3,    { SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
  121.     { "CEVAL",    CEVAL,    EvalCurveObject,    2,    { CURVE_EXPR, NUMERIC_EXPR } },
  122.     { "STANGENT", STANGENT,    TangentSurfaceObject,    4,    { SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
  123.     { "CTANGENT", CTANGENT,    TangentCurveObject,    2,    { CURVE_EXPR, NUMERIC_EXPR } },
  124.     { "SNORMAL",  SNORMAL,    NormalSurfaceObject,    3,    { SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
  125.     { "SDIVIDE",  SDIVIDE,    DivideSurfaceObject,    3,    { SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
  126.     { "CDIVIDE",  CDIVIDE,    DivideCurveObject,    2,    { CURVE_EXPR, NUMERIC_EXPR } },
  127.     { "SREGION",  SREGION,    RegionFromSurfaceObject, 4,    { SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
  128.     { "CREGION",  CREGION,    RegionFromCurveObject,    3,    { CURVE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
  129.     { "SREFINE",  SREFINE,    RefineSurfaceObject,    4,    { SURFACE_EXPR, NUMERIC_OBJ, NUMERIC_OBJ, OLST_EXPR } },
  130.     { "CREFINE",  CREFINE,    RefineCurveObject,    3,    { CURVE_EXPR, NUMERIC_OBJ, OLST_EXPR } },
  131.     { "SRAISE",   SRAISE,    RaiseSurfaceObject,    3,    { SURFACE_EXPR, NUMERIC_OBJ, NUMERIC_OBJ } },
  132.     { "CRAISE",   CRAISE,    RaiseCurveObject,    2,    { CURVE_EXPR, NUMERIC_OBJ } },
  133.     { "CSURFACE", CSURFACE,    CurveFromSurface,    3,    { SURFACE_EXPR, NUMERIC_OBJ, NUMERIC_OBJ } },
  134.     { "CMESH",    CMESH,    CurveFromSrfMesh,    3,    { SURFACE_EXPR, NUMERIC_OBJ, NUMERIC_OBJ } },
  135.     { "NTH",      NTH,        GetNthList,        2,    { OLST_EXPR, NUMERIC_EXPR } },
  136.     { "GPOLYGON", GPOLYGON,    Geometry2Polygons,    1,    { OLST_GEOM_EXPR } },
  137.     { "GPOLYLINE", GPOLYLINE,    Geometry2Polylines,    1,    { OLST_GEOM_EXPR } },
  138.     { "CIRCLE",   CIRCLE,    GenCircleCurveObject,    2,    { VECTOR_EXPR, NUMERIC_EXPR } },
  139.     { "ARC",      ARC,        GenArcCurveObject,    3,    { VECTOR_EXPR, VECTOR_EXPR, VECTOR_EXPR } },
  140.     { "RULEDSRF", RULEDSRF,    GenRuledSrfObject,    2,    { CURVE_EXPR, CURVE_EXPR } },
  141.     { "BOOLSUM",  BOOLSUM,    GenBoolSumSrfObject,    4,    { CURVE_EXPR, CURVE_EXPR, CURVE_EXPR, CURVE_EXPR } },
  142.     { "SFROMCRVS", SFROMCRVS,    GenSrfFromCrvsObject,    1,    { OLST_EXPR } },
  143.     { "SWEEPSRF", SWEEPSRF,    GenSweepSrfObject,    3,    { CURVE_EXPR, CURVE_EXPR, CURVE_EXPR | NUMERIC_EXPR } },
  144.     { "OFFSET",      OFFSET,    GenOffsetObject,    2,    { CURVE_EXPR | SURFACE_EXPR, NUMERIC_EXPR } },
  145.     { "CEDITPT",  CEDITPT,    EditCrvControlPoint,    3,    { CURVE_EXPR, CTLPT_EXPR, NUMERIC_EXPR } },
  146.     { "SEDITPT",  SEDITPT,    EditSrfControlPoint,    4,    { SURFACE_EXPR, CTLPT_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
  147.     { "MERGEPOLY",MERGEPOLY,    GenObjectFromPolyList,    1,    { OLST_EXPR } },
  148. };
  149. int ObjFuncTableSize = sizeof(ObjFuncTable) / sizeof(ObjFuncTableType);
  150.  
  151. /* The cast for DosSystem below is because of the xlc compiler for the R6000 */
  152. /* aix system complains on DosSystem as function with no arguments, so we    */
  153. /* make it think it has one integer argument...                     */
  154. typedef void (*VoidFuncIntPtr)(int);
  155. GenFuncTableType GenFuncTable[] = {
  156.     { "EXIT",    EXIT,        MyExit,            0,    { 0 } },
  157.     { "VIEW",    VIEW,        WndwViewGeomObject,    2,    { OLST_GEOM_EXPR, NUMERIC_EXPR } },
  158.     { "DIR",    DIR,        DosPrintDir,        1,    { STRING_EXPR } },
  159.     { "CHDIR",    CHDIR,        DosChangeDir,        1,    { STRING_EXPR } },
  160.     { "NORMAL",    NORMAL,        ViewSetNormals,        3,    { NUMERIC_EXPR,    NUMERIC_EXPR, NUMERIC_EXPR } },
  161.     { "INCLUDE", INCLUDE,    FileInclude,        1,    { STRING_EXPR } },
  162.     { "SAVE",    SAVE,        DataPrsrPutObject,    2,    { STRING_EXPR, ANY_EXPR } },
  163.     { "FREE",    FREEOBJ,    FreeObject,        1,    { ANY_EXPR } },
  164.     { "INTERACT", INTERACT,     InteractPolyObject,    2,    { OLST_GEOM_EXPR, NUMERIC_EXPR } },
  165.     { "PAUSE",    PAUSE,        WndwPause,        1,    { NUMERIC_EXPR } },
  166.     { "IF",    IFCOND,     IfCondition,        4,    { NUMERIC_EXPR,    STRING_EXPR, NUMERIC_EXPR, ANY_EXPR } },
  167.     { "FOR",    FORLOOP,     ForLoop,        4,    { NUMERIC_EXPR,    NUMERIC_EXPR, NUMERIC_EXPR, ANY_EXPR } },
  168.     { "HELP",    PRHELP,        PrintHelp,        1,    { STRING_EXPR } },
  169.     { "VARLIST", VARLIST,     PrintObjectList,    0,    { 0 } },
  170.     { "ALIAS",    ALIAS,        AliasEdit,        2,    { STRING_EXPR, STRING_EXPR } },
  171.     { "BEEP",    BEEP,       GGTone,            2,    { NUMERIC_EXPR, NUMERIC_EXPR } },
  172.     { "EDIT",    EDIT,        DosEditFile,        1,    { STRING_EXPR } },
  173.     { "SYSTEM",    SYSTEM,        (VoidFuncIntPtr) DosSystem, 0,   { 0 } },
  174.     { "LOGFILE", LOGFILE,     WndwLogPrint,        1,    { NUMERIC_EXPR } },
  175.     { "COLOR",    COLOR,        SetObjectColor,     2,    { GEOM_EXPR, NUMERIC_EXPR } },
  176.     { "SNOC",    SNOC,        SnocList,        2,    { ANY_EXPR, OLST_EXPR } },
  177.     { "ATTRIB",    ATTRIB,        SetObjectStrAttrib,    3,    { GEOM_EXPR, STRING_EXPR, STRING_EXPR } },
  178.     { "CLOSED", CLOSED,        ViewSetClosed,        1,    { NUMERIC_EXPR } }
  179. };
  180. int GenFuncTableSize = sizeof(GenFuncTable) / sizeof(GenFuncTableType);
  181.  
  182. ConstantTableType ConstantTable[] = {
  183.     { "PI",    M_PI },
  184.  
  185.     { "ON",    1.0 },
  186.     { "TRUE",    1.0 },
  187.     { "OFF",    0.0 },
  188.     { "FALSE",    0.0 },
  189.  
  190.     { "COL",    (double) CAGD_CONST_U_DIR },
  191.     { "ROW",    (double) CAGD_CONST_V_DIR },
  192.  
  193.     { "KV_OPEN", (double) KV_UNIFORM_OPEN },
  194.     { "KV_FLOAT", (double) KV_UNIFORM_FLOAT },
  195.  
  196.     { "E2",     (double) CAGD_PT_E2_TYPE },
  197.     { "E3",     (double) CAGD_PT_E3_TYPE },
  198.     { "P2",     (double) CAGD_PT_P2_TYPE },
  199.     { "P3",     (double) CAGD_PT_P3_TYPE },
  200.  
  201.     { "BLACK",  (double) BLACK },
  202.     { "BLUE",    (double) BLUE },
  203.     { "GREEN",    (double) GREEN },
  204.     { "CYAN",    (double) CYAN },
  205.     { "RED",    (double) RED },
  206.     { "MAGENTA", (double) MAGENTA },
  207.     { "YELLOW", (double) YELLOW },
  208.     { "WHITE",  (double) WHITE },
  209.  
  210.     { "MSDOS",  (double) MACHINE_MSDOS },
  211.     { "SGI",    (double) MACHINE_SGI },
  212.     { "HP",     (double) MACHINE_HP },
  213.     { "SUN",    (double) MACHINE_SUN },
  214.     { "APOLLO", (double) MACHINE_APOLLO },
  215.     { "UNIX",   (double) MACHINE_UNIX },
  216. };
  217. int ConstantTableSize = sizeof(ConstantTable) / sizeof(ConstantTableType);
  218.  
  219. /*****************************************************************************
  220. *   Routine to do type checking to the given tree - return type if found one *
  221. * or returns ERROR_EXPR if error in types was detected.                 *
  222. *****************************************************************************/
  223. IritExprType InptPrsrTypeCheck(ParseTree *Root, int Level)
  224. {
  225.     IritExprType Right, Left, Result;
  226.  
  227.     if (Level == 0 &&
  228.     Root->NodeKind != PARAMETER &&        /* What is allowed on top level. */
  229.     Root->NodeKind != EQUAL &&
  230.     !IS_GEN_FUNCTION(Root->NodeKind)) {
  231.     IPGlblEvalError = IE_ERR_NO_ASSIGNMENT;
  232.     strcpy(IPGlblCharData, "");
  233.     return ERROR_EXPR;
  234.     }
  235.  
  236.     if (IS_NUM_FUNCTION(Root->NodeKind)) { /* Funcs which returns Real Type: */
  237.     if (FuncParamMismatch(Root)) return ERROR_EXPR;
  238.     return NUMERIC_EXPR;
  239.     }
  240.  
  241.     if (IS_GEN_FUNCTION(Root->NodeKind)) {   /* Funcs which returns nothing: */
  242.     if (Level == 0) {
  243.         if (FuncParamMismatch(Root)) return ERROR_EXPR;
  244.         return NO_EXPR;
  245.     }
  246.     else {
  247.         IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
  248.         UpdateCharError("Procedure ", Root->NodeKind);
  249.         return ERROR_EXPR;
  250.     }
  251.     }
  252.  
  253.     switch (Root->NodeKind) {
  254.     case VECTOR:          /* Object functions which returns Vector Type: */
  255.     case STANGENT:
  256.     case CTANGENT:
  257.     case SNORMAL:
  258.         if (FuncParamMismatch(Root)) return ERROR_EXPR;
  259.         return VECTOR_EXPR;
  260.     case CTLPT:          /* Object functions which returns Ctl Pt Type: */
  261.     case CEVAL:
  262.     case SEVAL:
  263.         if (FuncParamMismatch(Root)) return ERROR_EXPR;
  264.         return CTLPT_EXPR;
  265.     case ROTX:
  266.     case ROTY:
  267.     case ROTZ:
  268.     case TRANS:
  269.     case SCALE:
  270.         if (FuncParamMismatch(Root)) return ERROR_EXPR;
  271.         return MATRIX_EXPR;
  272.     case BOX:
  273.     case GBOX:
  274.     case CONE:
  275.     case CONE2:
  276.     case CYLIN:
  277.     case SPHERE:
  278.     case TORUS:
  279.     case CIRCPOLY:
  280.     case POLY:
  281.     case CROSSEC:
  282.     case CONVEX:
  283.     case GPOLYGON:
  284.     case GPOLYLINE:
  285.     case MERGEPOLY:
  286.         if (FuncParamMismatch(Root)) return ERROR_EXPR;
  287.         return POLY_EXPR;
  288.     case CBEZIER:
  289.     case CBSPLINE:
  290.     case CREFINE:
  291.     case CRAISE:
  292.     case CSURFACE:
  293.     case CMESH:
  294.     case CIRCLE:
  295.     case ARC:
  296.     case CREGION:
  297.     case CEDITPT:
  298.         if (FuncParamMismatch(Root)) return ERROR_EXPR;
  299.         return CURVE_EXPR;
  300.     case SBEZIER:
  301.     case SBSPLINE:
  302.     case SREFINE:
  303.     case SRAISE:
  304.     case RULEDSRF:
  305.     case BOOLSUM:
  306.     case SWEEPSRF:
  307.     case SREGION:
  308.     case SFROMCRVS:
  309.     case SEDITPT:
  310.         if (FuncParamMismatch(Root)) return ERROR_EXPR;
  311.         return SURFACE_EXPR;
  312.     case LOAD:
  313.     case NTH:
  314.         if (FuncParamMismatch(Root)) return ERROR_EXPR;
  315.         return ANY_EXPR;
  316.     case OFFSET:
  317.         if (FuncParamMismatch(Root)) return ERROR_EXPR;
  318.         return SURFACE_EXPR | CURVE_EXPR;
  319.     case SURFREV:
  320.     case EXTRUDE:
  321.         if (FuncParamMismatch(Root)) return ERROR_EXPR;
  322.         return SURFACE_EXPR | POLY_EXPR;
  323.     case LIST:
  324.     case SDIVIDE:
  325.     case CDIVIDE:
  326.         if (FuncParamMismatch(Root)) return ERROR_EXPR;
  327.         return OLST_EXPR;
  328.     case PLUS:
  329.     case MINUS:
  330.     case MULT:
  331.     case DIV:
  332.     case POWER:
  333.         Right = InptPrsrTypeCheck(Root->Right, Level+1);
  334.         Left  = InptPrsrTypeCheck(Root->Left,  Level+1);
  335.         if (Right == ERROR_EXPR || Left == ERROR_EXPR) return ERROR_EXPR;
  336.         if (!OverLoadTypeCheck(Root->NodeKind, Right, Left, &Result)) {
  337.         IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
  338.                 UpdateCharError("Operator ", Root->NodeKind);
  339.         return ERROR_EXPR;
  340.         }
  341.         else
  342.         return Result;
  343.     case UNARMINUS:
  344.         if ((Right = InptPrsrTypeCheck(Root->Right, Level+1)) == ERROR_EXPR)
  345.         return ERROR_EXPR;
  346.         else if (!OverLoadTypeCheck(Root->NodeKind, Right, NO_EXPR,
  347.                                 &Result)) {
  348.         IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
  349.                 UpdateCharError("Operator ", Root->NodeKind);
  350.         return ERROR_EXPR;
  351.         }
  352.         else
  353.         return Result;
  354.     case EQUAL:
  355.         if ((Right = InptPrsrTypeCheck(Root->Right, Level+1)) == ERROR_EXPR)
  356.         return ERROR_EXPR;
  357.         if (Root->Left->NodeKind != PARAMETER) {
  358.         IPGlblEvalError = IE_ERR_ASSIGN_LEFT_OP;
  359.         InptPrsrPrintTree(Root->Left, IPGlblCharData);
  360.         return ERROR_EXPR;
  361.         }
  362.         return Right;
  363.     case NUMBER:
  364.         return NUMERIC_EXPR;
  365.     case PARAMETER:
  366.         switch (Root->U.PObj->ObjType) {
  367.                 case POLY_OBJ:
  368.                     return POLY_EXPR;
  369.         case NUMERIC_OBJ:
  370.             return NUMERIC_EXPR;
  371.         case VECTOR_OBJ:
  372.             return VECTOR_EXPR;
  373.         case CTLPT_OBJ:
  374.             return CTLPT_EXPR;
  375.         case MATRIX_OBJ:
  376.             return MATRIX_EXPR;
  377.         case STRING_OBJ:
  378.             return STRING_EXPR;
  379.         case OBJ_LIST_OBJ:
  380.             return OLST_EXPR;
  381.         case CURVE_OBJ:
  382.             return CURVE_EXPR;
  383.         case SURFACE_OBJ:
  384.             return SURFACE_EXPR;
  385.         case UNDEF_OBJ:
  386.             IPGlblEvalError = IE_ERR_UNDEF_OBJECT;
  387.             strcpy(IPGlblCharData, Root->U.PObj->Name);
  388.             return ERROR_EXPR;
  389.         }
  390.         IPGlblEvalError = IE_ERR_FATAL_ERROR;
  391.         sprintf(IPGlblCharData, "Object = %s, Type %d",
  392.                 Root->U.PObj->Name, Root->U.PObj->ObjType);
  393.         return ERROR_EXPR;
  394.     case STRING:
  395.         return STRING_EXPR;
  396.     default:                     /* Should never happen. */
  397.         IPGlblEvalError = IE_ERR_FATAL_ERROR;
  398.             UpdateCharError("Token ", Root->NodeKind);
  399.         return ERROR_EXPR;
  400.     }
  401. }
  402.  
  403. /* Disable the function with no prototype warning on Borland's compilers. */
  404. #ifdef __BORLANDC__
  405. #pragma warn -pro
  406. #endif /* __BORLANDC__ */
  407.  
  408. /*****************************************************************************
  409. *   Routine to evaluate    a value    of a given tree    root and parameter.         *
  410. * Note we change the tree itself during the evaluation process.             *
  411. * Also note we assume the tree is type checked (via InptPrsrTypeCheck rtn).  *
  412. *****************************************************************************/
  413. ParseTree *InptPrsrEvalTree(ParseTree *Root, int Level)
  414. {
  415.     char *ErrorMsg;
  416.     RealType R;
  417.     ParseTree *TempL, *TempR, *Params[5];
  418.     PolygonStruct *PPoly;
  419.     ObjectStruct *PObj;
  420.  
  421.     switch (Root->NodeKind) {
  422.     case ARCSIN:       /* Real return functions with one real parameter. */
  423.     case ARCCOS:
  424.     case ARCTAN:
  425.     case COS:
  426.     case EXP:
  427.     case FABS:
  428.     case LN:
  429.     case LOG:
  430.     case SIN:
  431.     case SQRT:
  432.     case TAN:
  433.     case TIME:
  434.         if (!FetchParameters(Root, 1, Level, Params)) return NULL;
  435.         /* Use table entries to call the function directly. */
  436.         Root->U.R = (NumFuncTable[Root->NodeKind-NUM_FUNC_OFFSET].Func)
  437.                                  (Params[0]->U.R);
  438.         Root->ObjType = NUMERIC_OBJ;
  439.         if (RetrieveMathError()) return NULL;
  440.         return Root;
  441.  
  442.     case CPOLY:
  443.     case AREA:
  444.     case VOLUME:
  445.         if (!FetchParameters(Root, 1, Level, Params)) return NULL;
  446.         /* Use table entries to call the function directly. */
  447.         Root->U.R = (NumFuncTable[Root->NodeKind-NUM_FUNC_OFFSET].Func)
  448.                                      (Params[0]->U.PObj);
  449.         Root->ObjType = NUMERIC_OBJ;
  450.         if (RetrieveMathError()) return NULL;
  451.         return Root;
  452.  
  453.     case ARCTAN2:      /* Real return functions with two real parameters. */
  454.         if (!FetchParameters(Root, 2, Level, Params)) return NULL;
  455.         /* Use table entries to call the function directly. */
  456.         Root->U.R = (NumFuncTable[Root->NodeKind-NUM_FUNC_OFFSET].Func)
  457.                          (Params[0]->U.R, Params[1]->U.R);
  458.         Root->ObjType = NUMERIC_OBJ;
  459.         if (RetrieveMathError()) return NULL;
  460.         return Root;
  461.  
  462.     case VECTOR:  /* Object return functions with three real parameters. */
  463.         if (!FetchParameters(Root, 3, Level, Params)) return NULL;
  464.         /* Use table entries to call the function directly. */
  465.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  466.         ("", &Params[0]->U.R, &Params[1]->U.R, &Params[2]->U.R, NULL);
  467.         Root->ObjType = Root -> U.PObj -> ObjType;
  468.         return Root;
  469.  
  470.     case CTLPT:
  471.     case LIST:
  472.         /* Use table entries to call the function directly. */
  473.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  474.                                    (Root -> Right);
  475.         if (Root->U.PObj == NULL) return NULL;
  476.         Root->ObjType = Root -> U.PObj -> ObjType;
  477.         return Root;
  478.  
  479.     case ROTX:
  480.     case ROTY:
  481.     case ROTZ:
  482.         if (!FetchParameters(Root, 1, Level, Params)) return NULL;
  483.         /* Use table entries to call the function directly. */
  484.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  485.                                  (&Params[0]->U.R);
  486.         if (RetrieveMathError()) return NULL;
  487.         Root->ObjType = Root -> U.PObj -> ObjType;
  488.         return Root;
  489.  
  490.     case TRANS:
  491.     case SCALE:
  492.         if (!FetchParameters(Root, 1, Level, Params)) return NULL;
  493.         /* Use table entries to call the function directly. */
  494.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  495.                             (Params[0]->U.PObj->U.Vec);
  496.         if (RetrieveMathError()) return NULL;
  497.         Root->ObjType = Root -> U.PObj -> ObjType;
  498.         return Root;
  499.  
  500.     case BOX:
  501.         if (!FetchParameters(Root, 4, Level, Params)) return NULL;
  502.         /* Use table entries to call the function directly. */
  503.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  504.         (Params[0]->U.PObj->U.Vec, &Params[1]->U.R, &Params[2]->U.R,
  505.                                         &Params[3]->U.R);
  506.         Root->ObjType = Root -> U.PObj -> ObjType;
  507.         return Root;
  508.  
  509.     case GBOX:
  510.         if (!FetchParameters(Root, 4, Level, Params)) return NULL;
  511.         /* Use table entries to call the function directly. */
  512.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  513.         (Params[0]->U.PObj->U.Vec, Params[1]->U.PObj ->U.Vec,
  514.          Params[2]->U.PObj->U.Vec, Params[3]->U.PObj ->U.Vec);
  515.         Root->ObjType = Root -> U.PObj -> ObjType;
  516.         return Root;
  517.  
  518.     case CONE:
  519.     case CYLIN:
  520.     case CIRCPOLY:
  521.         if (!FetchParameters(Root, 3, Level, Params)) return NULL;
  522.         /* Use table entries to call the function directly. */
  523.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  524.         (Params[0]->U.PObj->U.Vec, Params[1]->U.PObj->U.Vec,
  525.                                     &Params[2]->U.R);
  526.         Root->ObjType = Root -> U.PObj -> ObjType;
  527.         return Root;
  528.  
  529.     case SPHERE:
  530.     case CIRCLE:
  531.         if (!FetchParameters(Root, 2, Level, Params)) return NULL;
  532.         /* Use table entries to call the function directly. */
  533.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  534.                        (Params[0]->U.PObj->U.Vec, &Params[1]->U.R);
  535.         Root->ObjType = Root -> U.PObj -> ObjType;
  536.         return Root;
  537.  
  538.     case TORUS:
  539.     case CONE2:
  540.         if (!FetchParameters(Root, 4, Level, Params)) return NULL;
  541.         /* Use table entries to call the function directly. */
  542.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  543.         (Params[0]->U.PObj->U.Vec, Params[1]->U.PObj->U.Vec,
  544.          &Params[2]->U.R, &Params[3]->U.R);
  545.         Root->ObjType = Root -> U.PObj -> ObjType;
  546.         return Root;
  547.  
  548.     case SEVAL:
  549.     case SNORMAL:
  550.         if (!FetchParameters(Root, 3, Level, Params)) return NULL;
  551.         /* Use table entries to call the function directly. */
  552.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  553.               (Params[0]->U.PObj, &Params[1]->U.R, &Params[2]->U.R);
  554.         if (Root->U.PObj == NULL) return NULL;
  555.         Root->ObjType = Root -> U.PObj -> ObjType;
  556.         return Root;
  557.  
  558.     case STANGENT:
  559.     case SREGION:
  560.         if (!FetchParameters(Root, 4, Level, Params)) return NULL;
  561.         /* Use table entries to call the function directly. */
  562.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  563.               (Params[0]->U.PObj, &Params[1]->U.R,
  564.                &Params[2]->U.R, &Params[3]->U.R);
  565.         if (Root->U.PObj == NULL) return NULL;
  566.         Root->ObjType = Root -> U.PObj -> ObjType;
  567.         return Root;
  568.  
  569.     case CDIVIDE:
  570.     case CEVAL:
  571.     case CTANGENT:
  572.     case CRAISE:
  573.     case OFFSET:
  574.         if (!FetchParameters(Root, 2, Level, Params)) return NULL;
  575.         /* Use table entries to call the function directly. */
  576.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  577.               (Params[0]->U.PObj, &Params[1]->U.R);
  578.         if (Root->U.PObj == NULL) return NULL;
  579.         Root->ObjType = Root -> U.PObj -> ObjType;
  580.         return Root;
  581.  
  582.     case SREFINE:
  583.         if (!FetchParameters(Root, 4, Level, Params)) return NULL;
  584.         /* Use table entries to call the function directly. */
  585.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  586.                (Params[0]->U.PObj, &Params[1]->U.R,
  587.                                     &Params[2]->U.R, Params[3]->U.PObj);
  588.         if (Root->U.PObj == NULL) return NULL;
  589.         Root->ObjType = Root -> U.PObj -> ObjType;
  590.         return Root;
  591.  
  592.     case CREFINE:
  593.         if (!FetchParameters(Root, 3, Level, Params)) return NULL;
  594.         /* Use table entries to call the function directly. */
  595.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  596.              (Params[0]->U.PObj, &Params[1]->U.R, Params[2]->U.PObj);
  597.         if (Root->U.PObj == NULL) return NULL;
  598.         Root->ObjType = Root -> U.PObj -> ObjType;
  599.         return Root;
  600.  
  601.     case SDIVIDE:
  602.     case SRAISE:
  603.     case CSURFACE:
  604.     case CREGION:
  605.         if (!FetchParameters(Root, 3, Level, Params)) return NULL;
  606.         /* Use table entries to call the function directly. */
  607.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  608.            (Params[0]->U.PObj, &Params[1]->U.R, &Params[2]->U.R);
  609.         if (Root->U.PObj == NULL) return NULL;
  610.         Root->ObjType = Root -> U.PObj -> ObjType;
  611.         return Root;
  612.  
  613.     case CMESH:
  614.         if (!FetchParameters(Root, 3, Level, Params)) return NULL;
  615.         /* Use table entries to call the function directly. */
  616.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  617.            (Params[0]->U.PObj,
  618.             &Params[1]->U.R, &Params[2]->U.R);
  619.         if (Root->U.PObj == NULL) return NULL;
  620.         Root->ObjType = Root -> U.PObj -> ObjType;
  621.         return Root;
  622.  
  623.     case NTH:
  624.         if (!FetchParameters(Root, 2, Level, Params)) return NULL;
  625.         /* Use table entries to call the function directly. */
  626.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  627.                         (Params[0]->U.PObj, &Params[1]->U.R);
  628.         if (Root->U.PObj == NULL) return NULL;
  629.  
  630.         if (IS_NUM_OBJ(Root->U.PObj)) {
  631.         Root->ObjType = NUMERIC_OBJ;
  632.         MyFree((char *) Root->U.PObj, ALLOC_OBJECT);
  633.         Root->U.R = Root->U.PObj->U.R;
  634.         Root->NodeKind = NUMBER;     /* Disconnect the var. binding. */
  635.         return Root;
  636.             }
  637.             else {
  638.         Root->ObjType = Root->U.PObj->ObjType;
  639.         /* Since at this point, no one is pointing on it: */
  640.         Root->U.PObj->Count = 0;
  641.         return Root;
  642.         }
  643.  
  644.     case POLY:
  645.     case SBEZIER:
  646.     case CBEZIER:
  647.     case SURFREV:
  648.     case CONVEX:
  649.     case GPOLYGON:
  650.     case GPOLYLINE:
  651.     case SFROMCRVS:
  652.     case MERGEPOLY:
  653.         if (!FetchParameters(Root, 1, Level, Params)) return NULL;
  654.         /* Use table entries to call the function directly. */
  655.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  656.                                (Params[0]->U.PObj);
  657.         if (Root->U.PObj == NULL) return NULL;
  658.         Root->ObjType = Root -> U.PObj -> ObjType;
  659.         return Root;
  660.  
  661.     case CBSPLINE:
  662.         if (!FetchParameters(Root, 3, Level, Params)) return NULL;
  663.         /* Use table entries to call the function directly. */
  664.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  665.             (&Params[0]->U.R, Params[1]->U.PObj, Params[2]->U.PObj);
  666.         if (Root->U.PObj == NULL) return NULL;
  667.         Root->ObjType = Root -> U.PObj -> ObjType;
  668.         return Root;
  669.  
  670.     case SBSPLINE:
  671.         if (!FetchParameters(Root, 4, Level, Params)) return NULL;
  672.         /* Use table entries to call the function directly. */
  673.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  674.             (&Params[0]->U.R, &Params[1]->U.R,
  675.              Params[2]->U.PObj, Params[3]->U.PObj);
  676.         if (Root->U.PObj == NULL) return NULL;
  677.         Root->ObjType = Root -> U.PObj -> ObjType;
  678.         return Root;
  679.  
  680.     case CROSSEC:
  681.         if (!FetchParameters(Root, 1, Level, Params)) return NULL;
  682.         Root->ObjType = POLY_OBJ;
  683.         /* Use table entries to call the function directly. */
  684.         if (IS_POLY_OBJ(Params[0] -> U.PObj))
  685.         Root->U.PObj =
  686.             (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  687.             (Params[0]->U.PObj);
  688.         else
  689.         Root->U.PObj =
  690.             (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)(NULL);
  691.         if (Root->U.PObj == NULL) return NULL;
  692.         return Root;
  693.  
  694.     case EXTRUDE:
  695.         if (!FetchParameters(Root, 2, Level, Params)) return NULL;
  696.         /* Use table entries to call the function directly. */
  697.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  698.                  (Params[0]->U.PObj, Params[1]->U.PObj->U.Vec);
  699.         if (Root->U.PObj == NULL) return NULL;
  700.         Root->ObjType = Root -> U.PObj -> ObjType;
  701.         return Root;
  702.  
  703.     case RULEDSRF:
  704.         if (!FetchParameters(Root, 2, Level, Params)) return NULL;
  705.         /* Use table entries to call the function directly. */
  706.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  707.                  (Params[0]->U.PObj, Params[1]->U.PObj);
  708.         if (Root->U.PObj == NULL) return NULL;
  709.         Root->ObjType = Root -> U.PObj -> ObjType;
  710.         return Root;
  711.  
  712.     case BOOLSUM:
  713.         if (!FetchParameters(Root, 4, Level, Params)) return NULL;
  714.         /* Use table entries to call the function directly. */
  715.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  716.                  (Params[0]->U.PObj, Params[1]->U.PObj,
  717.                   Params[2]->U.PObj, Params[3]->U.PObj);
  718.         if (Root->U.PObj == NULL) return NULL;
  719.         Root->ObjType = Root -> U.PObj -> ObjType;
  720.         return Root;
  721.  
  722.     case CEDITPT:
  723.         if (!FetchParameters(Root, 3, Level, Params)) return NULL;
  724.         /* Use table entries to call the function directly. */
  725.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  726.                  (Params[0]->U.PObj, Params[1]->U.PObj,
  727.                   &Params[2]->U.R);
  728.         if (Root->U.PObj == NULL) return NULL;
  729.         Root->ObjType = Root -> U.PObj -> ObjType;
  730.         return Root;
  731.  
  732.     case SEDITPT:
  733.         if (!FetchParameters(Root, 4, Level, Params)) return NULL;
  734.         /* Use table entries to call the function directly. */
  735.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  736.                  (Params[0]->U.PObj, Params[1]->U.PObj,
  737.                   &Params[2]->U.R, &Params[3]->U.R);
  738.         if (Root->U.PObj == NULL) return NULL;
  739.         Root->ObjType = Root -> U.PObj -> ObjType;
  740.         return Root;
  741.  
  742.     case ARC:
  743.         if (!FetchParameters(Root, 3, Level, Params)) return NULL;
  744.         /* Use table entries to call the function directly. */
  745.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  746.                   (Params[0]->U.PObj->U.Vec, Params[1]->U.PObj->U.Vec,
  747.                              Params[2]->U.PObj->U.Vec);
  748.         if (Root->U.PObj == NULL) return NULL;
  749.         Root->ObjType = Root -> U.PObj -> ObjType;
  750.         return Root;
  751.  
  752.     case SWEEPSRF:
  753.         if (!FetchParameters(Root, 3, Level, Params)) return NULL;
  754.         /* Use table entries to call the function directly. */
  755.         if (IS_NUM_NODE(Params[2])) {
  756.             Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  757.              (Params[0]->U.PObj, Params[1]->U.PObj, NULL,
  758.                                    &Params[2]->U.R);
  759.         }
  760.         else {
  761.         R = 1.0;
  762.             Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  763.              (Params[0]->U.PObj, Params[1]->U.PObj, Params[2]->U.PObj,
  764.                                         &R);
  765.         }
  766.         if (Root->U.PObj == NULL) return NULL;
  767.         Root->ObjType = Root -> U.PObj -> ObjType;
  768.         return Root;
  769.  
  770.     case LOAD:
  771.         if (!FetchParameters(Root, 1, Level, Params)) return NULL;
  772.         /* Use table entries to call the function directly. */
  773.         Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
  774.                         (Params[0]->U.PObj->U.Str, "");
  775.         if (Root->U.PObj == NULL) {
  776.             DataPrsrParseError(&ErrorMsg);
  777.         IPGlblEvalError = IE_ERR_DATA_PRSR_ERROR;
  778.         strcpy(IPGlblCharData, ErrorMsg);
  779.         return NULL;
  780.         }
  781.         Root->ObjType = Root -> U.PObj -> ObjType;
  782.         return Root;
  783.  
  784.     case SNOC:
  785.         if (!FetchParameters(Root, 2, Level, Params)) return NULL;
  786.  
  787.         if (Params[0]->ObjType == NUMERIC_OBJ) {
  788.         PObj = GenNumObject("", &Params[0]->U.R, NULL);
  789.         /* Use table entries to call the function directly. */
  790.         (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
  791.                             (PObj, Params[1]->U.PObj);
  792.         MyFree((char *) PObj, ALLOC_OBJECT);
  793.         }
  794.         else {
  795.         /* Use table entries to call the function directly. */
  796.         (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
  797.                     (Params[0]->U.PObj, Params[1]->U.PObj);
  798.         }
  799.         Root->ObjType = UNDEF_OBJ;
  800.         return Root;
  801.  
  802.     case VIEW:
  803.     case INTERACT:
  804.         if (!FetchParameters(Root, 2, Level, Params)) return NULL;
  805.         Root->ObjType = UNDEF_OBJ;
  806.         /* Use table entries to call the function directly. */
  807.         (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
  808.                       (Params[0]->U.PObj, &Params[1]->U.R);
  809.         return Root;
  810.  
  811.     case COLOR:
  812.         if (!FetchParameters(Root, 2, Level, Params)) return NULL;
  813.         Root->ObjType = UNDEF_OBJ;
  814.         /* Use table entries to call the function directly. */
  815.         (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
  816.                 (Params[0]->U.PObj, REAL_TO_INT(Params[1]->U.R));
  817.         return Root;
  818.  
  819.     case EXIT:
  820.         /* Yes - we finished for today... */
  821.         (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)(0);
  822.  
  823.     case PAUSE:
  824.     case LOGFILE:
  825.     case CLOSED:
  826.         if (!FetchParameters(Root, 1, Level, Params)) return NULL;
  827.         /* Use table entries to call the function directly. */
  828.         (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
  829.                                       (&Params[0] -> U.R);
  830.         Root->ObjType = UNDEF_OBJ;
  831.         return Root;
  832.  
  833.     case VARLIST:
  834.     case SYSTEM:
  835.         /* Use table entries to call the function directly. */
  836.         (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)(GlblObjList);
  837.         Root->ObjType = UNDEF_OBJ;
  838.         return Root;
  839.  
  840.     case DIR:
  841.     case CHDIR:
  842.     case INCLUDE:
  843.     case PRHELP:
  844.     case EDIT:
  845.         if (!FetchParameters(Root, 1, Level, Params)) return NULL;
  846.         /* Use table entries to call the function directly. */
  847.         (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
  848.              (Params[0]->U.PObj->U.Str);
  849.         Root->ObjType = UNDEF_OBJ;
  850.         return Root;
  851.  
  852.     case SAVE:
  853.         if (!FetchParameters(Root, 2, Level, Params)) return NULL;
  854.         if (Params[1]->ObjType == NUMERIC_OBJ) {
  855.         PObj = GenNumObject("", &Params[1]->U.R, NULL);
  856.             /* Use table entries to call the function directly. */
  857.             (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
  858.                     (Params[0]->U.PObj->U.Str, PObj);
  859.         MyFree((char *) PObj, ALLOC_OBJECT);
  860.         }
  861.         else {
  862.         /* Use table entries to call the function directly. */
  863.         (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
  864.                 (Params[0]->U.PObj->U.Str, Params[1]->U.PObj);
  865.         }
  866.  
  867.         if (DataPrsrParseError(&ErrorMsg) != 0) {
  868.         IPGlblEvalError = IE_ERR_DATA_PRSR_ERROR;
  869.         strcpy(IPGlblCharData, ErrorMsg);
  870.         return NULL;
  871.         }
  872.         Root->ObjType = UNDEF_OBJ;
  873.         return Root;
  874.  
  875.     case BEEP:
  876.         if (!FetchParameters(Root, 2, Level, Params)) return NULL;
  877.         /* Use table entries to call the function directly. */
  878.         (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
  879.          (REAL_TO_INT(Params[0]->U.R), REAL_TO_INT(Params[1]->U.R));
  880.         Root->ObjType = UNDEF_OBJ;
  881.         return Root;
  882.  
  883.     case ALIAS:
  884.         if (!FetchParameters(Root, 2, Level, Params)) return NULL;
  885.         /* Use table entries to call the function directly. */
  886.         (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
  887.              (Params[0]->U.PObj->U.Str, Params[1]->U.PObj->U.Str);
  888.         Root->ObjType = UNDEF_OBJ;
  889.         return Root;
  890.  
  891.     case ATTRIB:
  892.         if (!FetchParameters(Root, 3, Level, Params)) return NULL;
  893.         /* Use table entries to call the function directly. */
  894.         (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
  895.             (Params[0]->U.PObj,
  896.              Params[1]->U.PObj->U.Str, Params[2]->U.PObj->U.Str);
  897.         Root->ObjType = UNDEF_OBJ;
  898.         return Root;
  899.  
  900.     case FREEOBJ:
  901.         if (!FetchParameters(Root, 1, Level, Params)) return NULL;
  902.         if ((TempR = InptPrsrEvalTree(Root->Right, Level+1)) == NULL)
  903.         return NULL;
  904.         if (TempR->ObjType == NUMERIC_OBJ) {
  905.         IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
  906.         strcpy(IPGlblCharData, "Func FREE, parameter 1");
  907.         return Root;
  908.         }
  909.         if (strlen(TempR->U.PObj->Name) == 0) {
  910.         IPGlblEvalError = IE_ERR_FREE_SIMPLE;
  911.                 UpdateCharError("Procedure ", FREEOBJ);
  912.         return Root;
  913.         }
  914.         /* Use table entries to call the function directly. */
  915.         (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
  916.                                   (TempR->U.PObj);
  917.         Root->ObjType = UNDEF_OBJ;
  918.         TempR->U.PObj = NULL;        /* Make sure its disconnected... */
  919.         return Root;
  920.  
  921.     case NORMAL:
  922.         if (!FetchParameters(Root, 3, Level, Params)) return NULL;
  923.         /* Use table entries to call the function directly. */
  924.         (GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
  925.                   (&Params[0]->U.R, &Params[1]->U.R, &Params[2]->U.R);
  926.         Root->ObjType = UNDEF_OBJ;
  927.         return Root;
  928.  
  929.     case IFCOND:
  930.         IfCondition(FetchParameter(Root->Right, 0, 4),
  931.             FetchParameter(Root->Right, 1, 4),
  932.             FetchParameter(Root->Right, 2, 4),
  933.             FetchParameter(Root->Right, 3, 4));
  934.         Root->ObjType = UNDEF_OBJ;
  935.         return Root;
  936.  
  937.     case FORLOOP:
  938.         ForLoop(FetchParameter(Root->Right, 0, 4),
  939.             FetchParameter(Root->Right, 1, 4),
  940.             FetchParameter(Root->Right, 2, 4),
  941.             FetchParameter(Root->Right, 3, 4));
  942.         Root->ObjType = UNDEF_OBJ;
  943.         return Root;
  944.  
  945.     case PLUS:
  946.     case MINUS:
  947.     case MULT:
  948.     case DIV:
  949.     case POWER:
  950.         if (((TempR = InptPrsrEvalTree(Root->Right, Level+1)) == NULL)
  951.          || ((TempL = InptPrsrEvalTree(Root->Left,  Level+1)) == NULL))
  952.         return NULL;
  953.         TempR = OverLoadEvalOper(Root, TempR, TempL,
  954.                     &IPGlblEvalError, IPGlblCharData);
  955.         if (RetrieveMathError())
  956.         return NULL;
  957.         else
  958.         return TempR;
  959.  
  960.     case UNARMINUS:
  961.         if ((TempR = InptPrsrEvalTree(Root->Right, Level+1)) == NULL)
  962.         return NULL;
  963.         TempR = OverLoadEvalOper(Root, TempR, NULL,
  964.                     &IPGlblEvalError, IPGlblCharData);
  965.         if (RetrieveMathError())
  966.             return NULL;
  967.         else
  968.         return TempR;
  969.  
  970.     case NUMBER:
  971.         Root->ObjType = NUMERIC_OBJ;
  972.             return Root;
  973.  
  974.     case PARAMETER:
  975.         if (Level == 0) {          /* If only object - print its content. */
  976.         Root->U.PObj->Count--;   /* Remove reference from this tree. */
  977.         PrintObject(Root->U.PObj);
  978.         Root->U.PObj->Count++;              /* Add reference back. */
  979.         Root->ObjType = Root->U.PObj->ObjType;
  980.         return Root;
  981.         }
  982.         if (IS_NUM_OBJ(Root->U.PObj)) {
  983.         Root->ObjType = NUMERIC_OBJ;
  984.         Root->U.PObj->Count--;
  985.         Root->U.R = Root->U.PObj->U.R;
  986.         Root->NodeKind = NUMBER;     /* Disconnect the var. binding. */
  987.         return Root;
  988.             }
  989.         else {
  990.         Root->ObjType = Root->U.PObj->ObjType;
  991.         return Root;
  992.         }
  993.  
  994.     case STRING:
  995.         Root->ObjType = STRING_OBJ;
  996.             return Root;
  997.  
  998.     case EQUAL:
  999.         if ((TempR = InptPrsrEvalTree(Root->Right, Level+1)) == NULL)
  1000.         return NULL;
  1001.         TempL = Root->Left;
  1002.         PPoly = NULL;
  1003.         if (IS_UNDEF_OBJ(TempL->U.PObj))          /* Its new object. */
  1004.         InsertObject(TempL->U.PObj);       /* Insert to global vars. */
  1005.         else if (IS_POLY_OBJ(TempL->U.PObj))    /* If old var. was poly. */
  1006.         PPoly = TempL->U.PObj->U.Pl.P;
  1007.  
  1008.             if (IS_NUM_NODE(TempR)) {
  1009.         TempL->ObjType = TempL->U.PObj->ObjType = NUMERIC_OBJ;
  1010.         TempL->U.PObj->U.R = TempR->U.R;
  1011.         }
  1012.             else {
  1013.         if (TempL -> U.PObj == TempR -> U.PObj) return TempR;/* A=A. */
  1014.         TempL->ObjType = TempR->ObjType;
  1015.         CopyObject(TempL->U.PObj, TempR->U.PObj, FALSE);
  1016.         }
  1017.         if (PPoly != NULL) MyFree((char *) (PPoly), ALLOC_POLYGON);
  1018.  
  1019.         Root->ObjType = UNDEF_OBJ;
  1020.         return TempR;
  1021.     }
  1022.     return NULL;                    /* Makes warning silent. */
  1023. }
  1024.  
  1025. /* Restore the function with no prototype warning on Borland's compilers. */
  1026. #ifdef __BORLANDC__
  1027. #pragma warn .pro
  1028. #endif /* __BORLANDC__ */
  1029.  
  1030. /*****************************************************************************
  1031. *   Routine to print help on the given subject HelpHeader.             *
  1032. * Note a match is if the HelpHeader in prefix of help file line.         *
  1033. *****************************************************************************/
  1034. static void PrintHelp(char *HelpHeader)
  1035. {
  1036.     int    i;
  1037.     char *Path, s[LINE_LEN];
  1038.     FILE *f;
  1039.  
  1040.     Path = searchpath(GlblHelpFileName);
  1041.  
  1042.     if (strlen(HelpHeader) == 0)
  1043.     HelpHeader = "Commands";        /* Print a list of all commands. */
  1044.  
  1045.     if ((f = fopen(Path, "r")) == NULL) {
  1046.     sprintf(s, "Cannot open help file \"%s\".\n", GlblHelpFileName);
  1047.     WndwInputWindowPutStr(s);
  1048.     return;
  1049.     }
  1050.  
  1051.     for (i = 0; i < (int) strlen(HelpHeader); i++)
  1052.     if (islower(HelpHeader[i])) HelpHeader[i] = toupper(HelpHeader[i]);
  1053.  
  1054.     while (fgets(s, LINE_LEN-1, f) != NULL) {
  1055.     if (strncmp(HelpHeader, s, strlen(HelpHeader)) == 0) {
  1056.         /* Found match - print it. */
  1057.         while (fgets(s, LINE_LEN-1, f) != NULL && s[0] != '$') {
  1058.         WndwInputWindowPutStr(&s[1]);             /* Skip char 1. */
  1059.         }
  1060.         fclose(f);
  1061.         return;
  1062.     }
  1063.     }
  1064.  
  1065.     fclose(f);
  1066.  
  1067.     sprintf(s, "No help on %s\n", HelpHeader);
  1068.     WndwInputWindowPutStr(s);
  1069. }
  1070.  
  1071. /*****************************************************************************
  1072. *   Routine to execute the IF structure.                     *
  1073. *****************************************************************************/
  1074. static void IfCondition(ParseTree *Left, ParseTree *Cond, ParseTree *Right,
  1075.                               ParseTree *PBody)
  1076. {
  1077.     int i, NumOfExpr;
  1078.     RealType L, R;
  1079.     char *Str;
  1080.  
  1081.     Left = InptPrsrEvalTree(Left, 1);
  1082.     Cond = InptPrsrEvalTree(Cond, 1);
  1083.     Right = InptPrsrEvalTree(Right, 1);
  1084.  
  1085.     L = Left->U.R;
  1086.     Str = Cond->U.PObj->U.Str;
  1087.     R = Right->U.R;
  1088.  
  1089.     if ((strcmp(Str, "=")  == 0 && L == R) ||
  1090.     (strcmp(Str, "<>") == 0 && L != R) ||
  1091.     (strcmp(Str, "<=") == 0 && L <= R) ||
  1092.     (strcmp(Str, ">=") == 0 && L >= R) ||
  1093.     (strcmp(Str, ">")  == 0 && L > R) ||
  1094.     (strcmp(Str, "<")  == 0 && L < R)) {
  1095.     /* If we are here, then the condition holds: */
  1096.     for (i = 0; i < (NumOfExpr = CountNumExpressions(PBody)); i++) {
  1097.         InptPrsrEvalTree(FetchExpression(PBody, i, NumOfExpr), 0);
  1098.         if (GlblWasCtrlBrk ||     /* async. break send from the user. */
  1099.         IPGlblEvalError) break;
  1100.     }
  1101.     }
  1102. }
  1103.  
  1104. /*****************************************************************************
  1105. *   Routine to execute the FOR structure loop.                     *
  1106. *   Note that as InptPrsrEvalTree routine is destructive on its input tree,  *
  1107. * we must make a copy of the body before executing it!                 *
  1108. *   We wish we could access the loop variable directly, but the user might   *
  1109. * be stupid and free it in the loop - so me must access it by name.         *
  1110. *****************************************************************************/
  1111. static void ForLoop(ParseTree *PStart, ParseTree *PInc, ParseTree *PEnd,
  1112.                             ParseTree *PBody)
  1113. {
  1114.     int i, NumOfExpr, LoopCount;
  1115.     char *LoopVarName = NULL;
  1116.     RealType LoopVar, StartVal, Increment, EndVal;
  1117.     ParseTree *PTemp;
  1118.     ObjectStruct *PLoopVar;
  1119.  
  1120.     /* Find the only two cases where loop variable is allowed - when then */
  1121.     /* given starting value is a parameter, or assignment to parameter... */
  1122.     if (PStart -> NodeKind == PARAMETER)
  1123.     LoopVarName = PStart -> U.PObj -> Name;
  1124.     else if (PStart -> NodeKind == EQUAL &&
  1125.          PStart -> Left -> NodeKind == PARAMETER) {
  1126.     LoopVarName = PStart -> Left -> U.PObj -> Name;
  1127.     /* Rebind the iteration variable to body - it might be new: */
  1128.     RebindVariable(PBody, PStart -> Left -> U.PObj);
  1129.     if (GetObject(LoopVarName) == NULL)        /* It is really new. */
  1130.         PStart -> Left -> U.PObj -> Count++;
  1131.     }
  1132.  
  1133.     PStart = InptPrsrEvalTree(PStart, 1);     /* Evaluate starting value. */
  1134.     PInc   = InptPrsrEvalTree(PInc, 1);        /* Evaluate increment value. */
  1135.     PEnd   = InptPrsrEvalTree(PEnd, 1);              /* Evaluate end value. */
  1136.     if (IPGlblEvalError ||
  1137.     PStart == NULL || PInc == NULL || PEnd == NULL) return;
  1138.     StartVal = PStart -> U.R;
  1139.     Increment = PInc -> U.R;
  1140.     EndVal = PEnd -> U.R;
  1141.  
  1142.     NumOfExpr = CountNumExpressions(PBody);    /* Num. of expr. in the body. */
  1143.     for (LoopVar = StartVal, LoopCount = 0;
  1144.     APX_EQ(LoopVar, EndVal) ||
  1145.     (Increment > 0 ? LoopVar <= EndVal : LoopVar >= EndVal);
  1146.     LoopVar += Increment, LoopCount++) {
  1147.     if (GlblWasCtrlBrk ||         /* Async. break send from the user. */
  1148.         IPGlblEvalError || GlblFatalError) return;
  1149.     if (LoopVarName != NULL) {
  1150.         if ((PLoopVar = GetObject(LoopVarName)) != NULL &&
  1151.          IS_NUM_OBJ(PLoopVar))
  1152.         PLoopVar -> U.R = LoopVar; /* Update loop var. */
  1153.         else {
  1154.         IPGlblEvalError = IE_ERR_MODIF_ITER_VAR;
  1155.         strcpy(IPGlblCharData, LoopVarName);
  1156.         }
  1157.     }
  1158.  
  1159.     for (i = 0; i < NumOfExpr; i++) {
  1160.         PTemp = FetchExpression(PBody, i, NumOfExpr);
  1161.         if (LoopCount == 0 && InptPrsrTypeCheck(PTemp, 0) == ERROR_EXPR)
  1162.         return;
  1163.         else {
  1164.         if (LoopVar == EndVal) {
  1165.             /* Use the original tree. Note we must evaluate the      */
  1166.             /* original tree at least once as ObjType's are updated. */
  1167.             InptPrsrEvalTree(PTemp, 0);     /* Eval as its top level... */
  1168.         }
  1169.         else {
  1170.             PTemp = InptPrsrCopyTree(PTemp);
  1171.             InptPrsrEvalTree(PTemp, 0);     /* Eval as its top level... */
  1172.             InptPrsrFreeTree(PTemp);         /* Not needed any more. */
  1173.         }
  1174.         }
  1175.     }
  1176.     }
  1177. }
  1178.  
  1179. /*****************************************************************************
  1180. *   Routine to create an OBJECT LIST object out of all parameters.         *
  1181. *****************************************************************************/
  1182. static ObjectStruct *GenObjectList(ParseTree *PObjParams)
  1183. {
  1184.     int i, NumOfParams;
  1185.     ParseTree *Param;
  1186.     ObjectStruct *PObj;
  1187.  
  1188.     NumOfParams = CountNumParameters(PObjParams);
  1189.     if (NumOfParams > MAX_OBJ_LIST) {
  1190.     IPGlblEvalError = IE_ERR_LIST_TOO_LONG;
  1191.     return NULL;
  1192.     }
  1193.  
  1194.     PObj = AllocObject("", OBJ_LIST_OBJ, NULL);
  1195.  
  1196.     for (i = 0; i < NumOfParams; i++) {
  1197.     if ((Param = InptPrsrEvalTree(FetchParameter(PObjParams, i,
  1198.                              NumOfParams),
  1199.                       1)) == NULL) {
  1200.         MyFree((char *) PObj, ALLOC_OBJECT);
  1201.         return NULL;
  1202.         }
  1203.     if (Param -> NodeKind == NUMBER ||
  1204.         (Param -> NodeKind == UNARMINUS &&
  1205.          Param -> ObjType == NUMERIC_OBJ)) {
  1206.         /* This is a special case in which the data is saved in parse    */
  1207.             /* tree instead of as an underneath object - make an object!     */
  1208.         PObj -> U.PObjList[i] = AllocObject("", NUMERIC_OBJ, NULL);
  1209.         PObj -> U.PObjList[i] -> U.R = Param -> U.R;
  1210.     }
  1211.         else {
  1212.         if (Param -> U.PObj -> ObjType == UNDEF_OBJ) {
  1213.         IPGlblEvalError = IE_ERR_UNDEF_OBJECT;
  1214.         strcpy(IPGlblCharData, Param -> U.PObj -> Name);
  1215.         PObj -> U.PObjList[i] = NULL;
  1216.         MyFree((char *) PObj, ALLOC_OBJECT);
  1217.         return NULL;
  1218.         }
  1219.  
  1220.         PObj -> U.PObjList[i] = Param -> U.PObj;
  1221.         Param -> U.PObj -> Count++;    /* Increase number of references. */
  1222.         }
  1223.     }
  1224.  
  1225.     if (NumOfParams < MAX_OBJ_LIST) PObj -> U.PObjList[NumOfParams] = NULL;
  1226.     return PObj;
  1227. }
  1228.  
  1229. /*****************************************************************************
  1230. *   Routine to create an Control Point Object out of all parameters.         *
  1231. *****************************************************************************/
  1232. static ObjectStruct *CtlPtFromParams(ParseTree *PObjParams)
  1233. {
  1234.     int i, NumPts, NumOfParams, PtType,
  1235.     CoordCount = 0;
  1236.     ParseTree *Param;
  1237.     ObjectStruct *PObj;
  1238.  
  1239.     NumOfParams = CountNumParameters(PObjParams);
  1240.  
  1241.     PObj = AllocObject("", CTLPT_OBJ, NULL);
  1242.  
  1243.     for (i = 0; i < NumOfParams; i++) {
  1244.     if ((Param = InptPrsrEvalTree(FetchParameter(PObjParams, i,
  1245.                              NumOfParams),
  1246.                       1)) == NULL) {
  1247.         MyFree((char *) PObj, ALLOC_OBJECT);
  1248.         return NULL;
  1249.         }
  1250.         if (Param -> ObjType != NUMERIC_OBJ) {
  1251.         IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
  1252.         strcpy(IPGlblCharData, "Numeric data expected");
  1253.         MyFree((char *) PObj, ALLOC_OBJECT);
  1254.         return NULL;
  1255.         }
  1256.  
  1257.     if (i == 0) {
  1258.         PtType = PObj -> U.CtlPt.PtType = (CagdPointType) Param -> U.R;
  1259.         switch (PtType) {
  1260.         case CAGD_PT_E2_TYPE:
  1261.             NumPts = 2;
  1262.             CoordCount = 1;
  1263.             break;
  1264.         case CAGD_PT_E3_TYPE:
  1265.             NumPts = 3;
  1266.             CoordCount = 1;
  1267.             break;
  1268.         case CAGD_PT_P2_TYPE:
  1269.             NumPts = 3;
  1270.             break;
  1271.         case CAGD_PT_P3_TYPE:
  1272.             NumPts = 4;
  1273.             break;
  1274.         default:
  1275.             IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
  1276.             strcpy(IPGlblCharData, "E2, E3, P2, P3 expected");
  1277.             MyFree((char *) PObj, ALLOC_OBJECT);
  1278.             return NULL;
  1279.         }
  1280.         if (NumOfParams - 1 != NumPts) {
  1281.         IPGlblEvalError = IE_ERR_NUM_PRM_MISMATCH;
  1282.         sprintf(IPGlblCharData, "%d expected", NumPts);
  1283.         MyFree((char *) PObj, ALLOC_OBJECT);
  1284.         return NULL;
  1285.         }
  1286.     }
  1287.         else
  1288.         PObj -> U.CtlPt.Coords[CoordCount++] = Param -> U.R;
  1289.     }
  1290.  
  1291.     return PObj;
  1292. }
  1293.  
  1294. /*****************************************************************************
  1295. *   Routine to count number of expressions seperated by a COLON are given    *
  1296. * in the tree ROOT. This routine is similar to CountNumParameters below.     *
  1297. *****************************************************************************/
  1298. static int CountNumExpressions(ParseTree *Root)
  1299. {
  1300.     int i=1;
  1301.  
  1302.     while (Root->NodeKind == COLON) {
  1303.     i++;
  1304.     Root = Root->Right;
  1305.     }
  1306.     return i;
  1307. }
  1308.  
  1309. /*****************************************************************************
  1310. *   Routine to fetch the i expression out of a tree represent n expressions  *
  1311. * (0 <= i < n) seperated by colonc. Similar to FetchParameter routine below. *
  1312. *****************************************************************************/
  1313. static ParseTree *FetchExpression(ParseTree *Root, int i, int n)
  1314. {
  1315.     int j;
  1316.  
  1317.     for (j = 0; j < i; j++) Root = Root->Right;
  1318.  
  1319.     if (i == n - 1)
  1320.         return Root;
  1321.     else
  1322.     return Root->Left;
  1323. }
  1324.  
  1325. /*****************************************************************************
  1326. *   Routine to retrieve math error if was one. return TRUE if was error.     *
  1327. *****************************************************************************/
  1328. static int RetrieveMathError(void)
  1329. {
  1330.     int Error;
  1331.     char *FuncName, *p;
  1332.  
  1333. #ifdef __MSDOS__
  1334.     if ((Error = MathError(&FuncName)) != 0) {
  1335.     switch (Error) {
  1336.         case DOMAIN:
  1337.         p = "DOMAIN";
  1338.         break;
  1339.         case SING:
  1340.         p = "SING";
  1341.         break;
  1342.         case OVERFLOW:
  1343.         p = "O.F.";
  1344.         break;
  1345.         case UNDERFLOW:
  1346.         p = "U.F.";
  1347.         break;
  1348.         case TLOSS:
  1349.         p = "TLOSS";
  1350.         break;
  1351.         default:
  1352.         p = "Undef.";
  1353.         break;
  1354.     }
  1355.         strcpy(IPGlblCharData, p);
  1356.     strcat(IPGlblCharData, " error - func. ");
  1357.     strcat(IPGlblCharData, FuncName);
  1358.     IPGlblEvalError = IE_ERR_FP_ERROR;
  1359.     return TRUE;
  1360.     }
  1361. #endif /* __MSDOS__ */
  1362.  
  1363.     return FALSE;
  1364. }
  1365.  
  1366. /*****************************************************************************
  1367. *  Routine to count number of parameters where given: parameters are defined *
  1368. * as subtrees seperated by commas, i.e.: the infix form 1, 2, 3, 4 is          *
  1369. * represented as [1, [2, [3, 4]]] in the tree supplied to this function and  *
  1370. * 4 (number of parameters) is returned.                         *
  1371. *****************************************************************************/
  1372. static int CountNumParameters(ParseTree *Root)
  1373. {
  1374.     int i = 1;
  1375.  
  1376.     if (Root == NULL) return 0;
  1377.  
  1378.     while (Root->NodeKind == COMMA) {
  1379.     i++;
  1380.     Root = Root->Right;
  1381.     }
  1382.     return i;
  1383. }
  1384.  
  1385. /*****************************************************************************
  1386. *   Routine to fetch the i paramter out of a tree represent n parameters     *
  1387. * (0 <= i < n). See CountNumParameters for more description of structure.    *
  1388. * Note it is assumed the tree HAS n parameters and 0<=i<n (No input error).  *
  1389. *****************************************************************************/
  1390. static ParseTree *FetchParameter(ParseTree *Root, int i, int n)
  1391. {
  1392.     int j;
  1393.  
  1394.     for (j = 0; j < i; j++) Root = Root->Right;
  1395.  
  1396.     if (i == n - 1)
  1397.     return Root;
  1398.     else
  1399.     return Root->Left;
  1400. }
  1401.  
  1402. /*****************************************************************************
  1403. *   Routine to fetch the parameters from the parsed tree.             *
  1404. * Returns TRUE iff fetching was succesfull.                     *
  1405. *****************************************************************************/
  1406. static int FetchParameters(ParseTree *Root, int NumParams, int Level,
  1407.                              ParseTree *Params[])
  1408. {
  1409.     int i;
  1410.  
  1411.     Level++;
  1412.     for (i = 0; i < NumParams; i++)
  1413.     if ((Params[i] =  InptPrsrEvalTree(FetchParameter(Root->Right, i,
  1414.                                  NumParams),
  1415.                       Level)) == NULL)
  1416.         return FALSE;
  1417.  
  1418.     return TRUE;
  1419. }
  1420.  
  1421. /*****************************************************************************
  1422. *   Routine to test number of parameters and type of them against what is    *
  1423. * defined in its global tables Num/Obj/GenFuncTable. return TRUE if mismatch *
  1424. * was detected:                                     *
  1425. *****************************************************************************/
  1426. static int FuncParamMismatch(ParseTree *Root)
  1427. {
  1428.     int FuncOffset, Count, i = Root->NodeKind / 100;
  1429.     FuncTableType *FuncTable;
  1430.  
  1431.     switch (i * 100) {
  1432.     case NUM_FUNC:               /* Numeric (real returned) functions. */
  1433.         FuncOffset = Root->NodeKind-NUM_FUNC_OFFSET;
  1434.         FuncTable = (FuncTableType *) NumFuncTable;
  1435.         break;
  1436.     case OBJ_FUNC:                 /* Object (returned) functions. */
  1437.         FuncOffset = Root->NodeKind-OBJ_FUNC_OFFSET;
  1438.         FuncTable = (FuncTableType *) ObjFuncTable;
  1439.         break;
  1440.     case GEN_FUNC:
  1441.         FuncOffset = Root->NodeKind-GEN_FUNC_OFFSET;
  1442.         FuncTable = (FuncTableType *) GenFuncTable;
  1443.         break;
  1444.     default:
  1445.         IPGlblEvalError = IE_ERR_FATAL_ERROR;
  1446.         UpdateCharError("Undefined function - ", Root->NodeKind);
  1447.         return TRUE;
  1448.     }
  1449.  
  1450.     if (FuncTable[FuncOffset].NumOfParam == ANY_PARAM_NUM)
  1451.     return FALSE;
  1452.  
  1453.     /* See if number of parameters is ok: */
  1454.     if ((Count = CountNumParameters(Root->Right)) !=
  1455.     FuncTable[FuncOffset].NumOfParam) {
  1456.     IPGlblEvalError = IE_ERR_NUM_PRM_MISMATCH;
  1457.     sprintf(IPGlblCharData, "Func %s - %d expected, %d found",
  1458.         FuncTable[FuncOffset].FuncName,
  1459.         FuncTable[FuncOffset].NumOfParam,
  1460.         Count);
  1461.     return TRUE;
  1462.     }
  1463.  
  1464.     /* See if type of parameters is consistent: */
  1465.     for (i = 0; i < Count; i++) {
  1466.     if (FuncTable[FuncOffset].ParamObjType[i] != ANY_EXPR &&
  1467.         !(FuncTable[FuncOffset].ParamObjType[i] &
  1468.           InptPrsrTypeCheck(FetchParameter(Root->Right, i, Count), 1))) {
  1469.         sprintf(IPGlblCharData, "Func %s,%sparameter %d",
  1470.             FuncTable[FuncOffset].FuncName,
  1471.             IPGlblEvalError == IE_ERR_UNDEF_OBJECT ? " undefined " : " ",
  1472.             i+1);
  1473.         IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
  1474.         return TRUE;
  1475.     }
  1476.     }
  1477.     return FALSE;
  1478. }
  1479.  
  1480. /*****************************************************************************
  1481. *   Routine to free a tree - release all memory    allocated by it.         *
  1482. *****************************************************************************/
  1483. void InptPrsrFreeTree(ParseTree *Root)
  1484. {
  1485.     char s[LINE_LEN];
  1486.     int ValidObject;
  1487.  
  1488.     if (!Root) return;
  1489.  
  1490.     ValidObject = Root->ObjType != NUMERIC_OBJ && Root->ObjType != UNDEF_OBJ;
  1491.  
  1492.     if (IS_FUNCTION(Root -> NodeKind)) {
  1493.     if (IS_NO_PARAM_FUNC(Root -> NodeKind))
  1494.         MyExprFree(Root);
  1495.     else {
  1496.         InptPrsrFreeTree(Root->Right);
  1497.         if (ValidObject && strlen(Root->U.PObj->Name) == 0)
  1498.         MyFree((char *) Root->U.PObj, ALLOC_OBJECT);     /* Its temp.*/
  1499.         MyExprFree(Root);
  1500.         }
  1501.     return;
  1502.     }
  1503.  
  1504.     switch (Root -> NodeKind) {
  1505.     case DIV:
  1506.     case MINUS:
  1507.     case MULT:
  1508.     case PLUS:
  1509.     case POWER:
  1510.         InptPrsrFreeTree(Root->Right);
  1511.         InptPrsrFreeTree(Root->Left);
  1512.         if (ValidObject && strlen(Root->U.PObj->Name) == 0)
  1513.         MyFree((char *) Root->U.PObj, ALLOC_OBJECT);/* Its temporary.*/
  1514.         MyExprFree(Root);
  1515.         break;
  1516.  
  1517.     case UNARMINUS:
  1518.         InptPrsrFreeTree(Root->Right);
  1519.         if (ValidObject && strlen(Root->U.PObj->Name) == 0)
  1520.         MyFree((char *) Root->U.PObj, ALLOC_OBJECT);/* Its temporary.*/
  1521.         MyExprFree(Root);
  1522.         break;
  1523.  
  1524.     case COMMA:
  1525.     case COLON:
  1526.     case EQUAL:
  1527.           InptPrsrFreeTree(Root->Right);
  1528.         InptPrsrFreeTree(Root->Left);
  1529.         MyExprFree(Root);
  1530.         break;
  1531.  
  1532.     case NUMBER:
  1533.         MyExprFree(Root);
  1534.         break;
  1535.  
  1536.     case PARAMETER:
  1537.         if (Root->U.PObj) {
  1538.         /* No assign took place -  Its temporary. */
  1539.         if ((Root->U.PObj->ObjType == UNDEF_OBJ ||
  1540.              strlen(Root->U.PObj->Name) == 0))
  1541.             MyFree((char *) Root->U.PObj, ALLOC_OBJECT);
  1542.         else
  1543.             Root->U.PObj->Count--;
  1544.         }
  1545.         MyExprFree(Root);
  1546.         break;
  1547.  
  1548.     case STRING:
  1549.         MyFree((char *) Root->U.PObj, ALLOC_OBJECT);/* The string object.*/
  1550.         MyExprFree(Root);
  1551.         break;
  1552.  
  1553.     case TOKENSTART:
  1554.         MyExprFree(Root);
  1555.         break;
  1556.  
  1557.     case OPENPARA:
  1558.     case CLOSPARA:
  1559.         MyExprFree(Root);
  1560.         break;
  1561.  
  1562.     default:
  1563.         /*   We might free partially build (by InptPrsr) tree when error */
  1564.         /* is detected, and such tree may have nodes with NodeKind>=1000.*/
  1565.         if (Root->NodeKind >= 1000) {
  1566.         MyExprFree(Root);
  1567.         }
  1568.         else {
  1569.         sprintf(s, "%s (%d).\n",
  1570.             "InptPrsrFreeTree: Undefined ParseTree type to free",
  1571.             Root -> NodeKind);
  1572.         FatalError(s);
  1573.         }
  1574.         break;
  1575.     }
  1576. }
  1577.  
  1578. /*****************************************************************************
  1579. *   Routine to print a content of ROOT (using inorder traversal):         *
  1580. * level    holds: 0 for lowest level +/-, 1 for *, /, 2 for ^ operations.         *
  1581. * If *str = NULL print on stderr, else on given    string Str.             *
  1582. *****************************************************************************/
  1583. void InptPrsrPrintTree(ParseTree *Root, char *Str)
  1584. {
  1585.     strcpy(IPGlblCharData, "");               /* Make the string empty. */
  1586.  
  1587.     if (Str == NULL) {
  1588.     strcpy(IPGlblCharData, "");           /* Make the string empty. */
  1589.     LocalPrintTree(Root, 0, IPGlblCharData);       /* Copy to local str. */
  1590.     fprintf(stderr, IPGlblCharData);             /* and print... */
  1591.     }
  1592.     else {
  1593.     strcpy(Str, "");               /* Make the string empty. */
  1594.     LocalPrintTree(Root, 0, Str); /* Dont print to stderr - copy to str. */
  1595.     }
  1596. }
  1597.  
  1598. /*****************************************************************************
  1599. *   Routine to print a content of ROOT (using inorder traversal):         *
  1600. * level    holds: 0 for lowest level +/-, 1 for *, /, 2 for ^ operations.         *
  1601. * It is assumed Str has at list LINE_LEN_LONG places to write the expression.*
  1602. *****************************************************************************/
  1603. static void LocalPrintTree(ParseTree *Root, int Level, char *Str)
  1604. {
  1605.     int    CloseFlag = FALSE, Len, i;
  1606.  
  1607.     if (!Root) return;
  1608.     i = Root->NodeKind / 100;
  1609.  
  1610.     if ((Len = strlen(Str)) > LINE_LEN_LONG * 2 / 3)/* Prevent from overflow.*/
  1611.     if (Str[Len-1] == '.')
  1612.         return;             /* "..." was allready concatenated. */
  1613.     else {
  1614.         strcat(Str, "...");
  1615.         return;
  1616.     }
  1617.  
  1618. #   ifdef DEBUG
  1619.     strcat(Str, "[");   /* Usefull to see ALL nestings - no preceedings. */
  1620. #   endif /* DEBUG */
  1621.  
  1622.     switch (i * 100) {
  1623.     case NUM_FUNC:
  1624.         Level = 0;
  1625.         CloseFlag = TRUE;
  1626.             strcat(Str, NumFuncTable[Root->NodeKind-NUM_FUNC_OFFSET].FuncName);
  1627.         strcat(Str, "(");
  1628.         break;
  1629.  
  1630.     case OBJ_FUNC:
  1631.         Level = 0;
  1632.         CloseFlag = TRUE;
  1633.             strcat(Str, ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].FuncName);
  1634.         strcat(Str, "(");
  1635.         break;
  1636.  
  1637.     case GEN_FUNC:
  1638.         Level = 0;
  1639.         CloseFlag = TRUE;
  1640.             strcat(Str, GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].FuncName);
  1641.         strcat(Str, "(");
  1642.         break;
  1643.  
  1644.     case OPERATORS:
  1645.         switch (Root->NodeKind) {
  1646.         case DIV:
  1647.             if (Level > 1) {
  1648.             strcat(Str, "(");
  1649.                 CloseFlag = TRUE;
  1650.             }
  1651.             Level = 1;                           /* Div Level. */
  1652.             LocalPrintTree(Root->Left, Level, Str);
  1653.             strcat(Str, "/");
  1654.             break;
  1655.  
  1656.         case MINUS:
  1657.             if (Level > 0) {
  1658.             strcat(Str, "(");
  1659.                 CloseFlag = TRUE;
  1660.             }
  1661.             Level = 0;                         /* Minus Level. */
  1662.             LocalPrintTree(Root->Left, Level, Str);
  1663.             strcat(Str, "-");
  1664.             break;
  1665.  
  1666.         case MULT:
  1667.             if (Level > 1) {
  1668.             strcat(Str, "(");
  1669.                 CloseFlag = TRUE;
  1670.             }
  1671.             Level = 1;                           /* Mul Level. */
  1672.             LocalPrintTree(Root->Left, Level, Str);
  1673.             strcat(Str, "*");
  1674.             break;
  1675.  
  1676.         case PLUS:
  1677.             if (Level > 0) {
  1678.             strcat(Str, "(");
  1679.                 CloseFlag = TRUE;
  1680.             }
  1681.             Level = 0;                          /* Plus Level. */
  1682.             LocalPrintTree(Root->Left, Level, Str);
  1683.             strcat(Str, "+");
  1684.             break;
  1685.  
  1686.         case POWER:
  1687.             Level = 2;                         /* Power Level. */
  1688.             LocalPrintTree(Root->Left, Level, Str);
  1689.             strcat(Str, "^");
  1690.             break;
  1691.  
  1692.         case UNARMINUS:
  1693.             strcat(Str, "(-");
  1694.             Level = 0;
  1695.             CloseFlag = TRUE;
  1696.             break;
  1697.  
  1698.         case COMMA:
  1699.             LocalPrintTree(Root->Left, Level, Str);
  1700.             strcat(Str, ",");
  1701.             break;
  1702.  
  1703.         case COLON:
  1704.             LocalPrintTree(Root->Left, Level, Str);
  1705.             strcat(Str, ":");
  1706.             break;
  1707.  
  1708.         case EQUAL:
  1709.             LocalPrintTree(Root->Left, Level, Str);
  1710.             strcat(Str, "=");
  1711.             break;
  1712.  
  1713.         case NUMBER:
  1714.             sprintf(&Str[strlen(Str)], "%lg", Root->U.R);
  1715.             break;
  1716.  
  1717.         case PARAMETER:
  1718.             sprintf(&Str[strlen(Str)], "%s", Root->U.PObj->Name);
  1719.             break;
  1720.  
  1721.         case STRING:
  1722.             sprintf(&Str[strlen(Str)], "\"%s\"", Root->U.PObj->U.Str);
  1723.             break;
  1724.  
  1725.         case OPENPARA:
  1726.             strcat(Str, "(");
  1727.             break;
  1728.  
  1729.         case CLOSPARA:
  1730.             strcat(Str, ")");
  1731.             break;
  1732.  
  1733.         case TOKENSTART:
  1734.             break;
  1735.  
  1736.         default:
  1737.             FatalError("LocalPrintTree: Undefined ParseTree type to print, exit");
  1738.             }
  1739.             break;
  1740.  
  1741.     default:
  1742.         FatalError("LocalPrintTree: Undefined ParseTree type to print, exit");
  1743.     }
  1744.     LocalPrintTree(Root->Right, Level, Str);
  1745.     if (CloseFlag) strcat(Str, ")");
  1746.  
  1747. #   ifdef DEBUG
  1748.     strcat(Str, "]");   /* Usefull to see ALL nestings - no preceedings. */
  1749. #   endif /* DEBUG */
  1750. }
  1751.  
  1752. /*****************************************************************************
  1753. *   Routine to copy a parse tree - Generate brand new ParseTree structure    *
  1754. * but bind to non-temp variables if they are exists - their Name is not NULL *
  1755. *   This means that updating these objects in the copied tree, will affect   *
  1756. * these objects in the original tree.                         *
  1757. *****************************************************************************/
  1758. ParseTree *InptPrsrCopyTree(ParseTree *Root)
  1759. {
  1760.     ParseTree *NewRoot;
  1761.  
  1762.     if (Root == NULL) return NULL;
  1763.  
  1764.     NewRoot = MyExprMalloc();
  1765.  
  1766.     if (IS_FUNCTION(Root->NodeKind)) {               /* All the functions. */
  1767.     NewRoot -> NodeKind = Root -> NodeKind;
  1768.     NewRoot -> ObjType = Root -> ObjType;
  1769.     NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
  1770.     return NewRoot;
  1771.     }
  1772.  
  1773.     switch (Root->NodeKind) {
  1774.     case DIV:
  1775.     case MINUS:
  1776.     case MULT:
  1777.     case PLUS:
  1778.     case POWER:
  1779.  
  1780.     case COMMA:
  1781.     case COLON:
  1782.     case EQUAL:
  1783.         NewRoot -> NodeKind = Root -> NodeKind;
  1784.         NewRoot -> ObjType = Root -> ObjType;
  1785.         NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
  1786.         NewRoot -> Left  = InptPrsrCopyTree(Root -> Left);
  1787.         return NewRoot;
  1788.  
  1789.     case NUMBER:
  1790.         NewRoot -> NodeKind = Root -> NodeKind;
  1791.         NewRoot -> ObjType = Root -> ObjType;
  1792.         NewRoot -> U.R = Root -> U.R;
  1793.         return NewRoot;
  1794.  
  1795.     case PARAMETER:
  1796.     case STRING:
  1797.         NewRoot -> NodeKind = Root -> NodeKind;
  1798.         NewRoot -> ObjType = Root -> ObjType;
  1799.         NewRoot -> U.PObj = Root -> U.PObj;        /* Point on SAME object. */
  1800.         NewRoot -> U.PObj -> Count++;    /* But increase its ref. count. */
  1801.         return NewRoot;
  1802.  
  1803.     case TOKENSTART:
  1804.         NewRoot -> NodeKind = Root -> NodeKind;
  1805.         NewRoot -> ObjType = Root -> ObjType;
  1806.         return NewRoot;
  1807.  
  1808.     default:
  1809.         FatalError("InptPrsrCopyTree: Undefined ParseTree type to copy, exit\n");
  1810.     }
  1811.     return NULL;                    /* Makes warning silent. */
  1812. }
  1813.  
  1814. /*****************************************************************************
  1815. *  Routine to rebind a variable - given a tree, scan it and update each      *
  1816. * occurance of that variable to point to PObj.                     *
  1817. *****************************************************************************/
  1818. static void RebindVariable(ParseTree *Root, ObjectStruct *PObj)
  1819. {
  1820.     if (Root == NULL) return;
  1821.  
  1822.     if (IS_FUNCTION(Root->NodeKind)) {               /* All the functions. */
  1823.     RebindVariable(Root -> Right, PObj);
  1824.     return;
  1825.     }
  1826.  
  1827.     switch (Root->NodeKind) {
  1828.     case UNARMINUS:
  1829.         RebindVariable(Root -> Right, PObj);
  1830.         return;
  1831.  
  1832.     case DIV:
  1833.     case MINUS:
  1834.     case MULT:
  1835.     case PLUS:
  1836.     case POWER:
  1837.  
  1838.     case COMMA:
  1839.     case COLON:
  1840.     case EQUAL:
  1841.         RebindVariable(Root -> Right, PObj);
  1842.         RebindVariable(Root -> Left, PObj);
  1843.         return;
  1844.  
  1845.     case NUMBER:
  1846.         return;
  1847.  
  1848.     case PARAMETER:
  1849.     case STRING:
  1850.         if (strcmp(Root -> U.PObj -> Name, PObj -> Name) == 0) {
  1851.         /* I wish I could free that, but nesting loops might try */
  1852.         /* to free the same place n times... We will loose this  */
  1853.         /* variable place if it defined for the first time. Fix  */
  1854.         /* it if you really care...                 */
  1855.         /*
  1856.         if (IS_UNDEF_OBJ(Root -> U.PObj))
  1857.             MyFree((char *) Root->U.PObj, ALLOC_OBJECT);
  1858.         */
  1859.         Root -> U.PObj = PObj;
  1860.         }
  1861.             return;
  1862.  
  1863.     case TOKENSTART:
  1864.         return;
  1865.  
  1866.     default:
  1867.         FatalError("RebindVariable: Undefined ParseTree type, exit\n");
  1868.     }
  1869. }
  1870.  
  1871. /*****************************************************************************
  1872. *   Routine to return evaluation error if happen one, zero elsewhere         *
  1873. *****************************************************************************/
  1874. InptPrsrEvalErrType InptPrsrEvalError(char **Message)
  1875. {
  1876.     InptPrsrEvalErrType Temp;
  1877.  
  1878.     *Message = IPGlblCharData;
  1879.     Temp = IPGlblEvalError;
  1880.     IPGlblEvalError = IPE_NO_ERR;
  1881.  
  1882.     return Temp;
  1883. }
  1884.